import processing.serial.*;

Serial myPort;

int maxDistance = 50;        // 最大检测距离 (cm)
int radius;                  // 雷达图半径 (像素)
PVector center;
int margin = 40;

float sweepAngle = 0;        // 当前扫描角度 (由串口更新)
ArrayList<Detection> detections = new ArrayList<Detection>();
ArrayList<Float> beamHistory = new ArrayList<Float>();
int beamTrailLength = 50;  // 保留最近30个角度
boolean sweepRightToLeft = false;
float lastSweepAngle = 0;

void setup() {
  size(640, 480);
  println(Serial.list());  // 查看串口列表
  

  // 请根据打印结果替换为你的端口号，如 Serial.list()[1]
  myPort = new Serial(this, Serial.list()[0], 9600);
  myPort.bufferUntil('\n');

  radius = min(width, height * 2) / 2 - margin;
  center = new PVector(width / 2, height - margin);
  smooth();
}

void draw() {
  background(0);
  drawRadarGrid();
  drawSweepBeam();
  drawDetections();
}

// --------------------- 串口数据处理 ---------------------

void serialEvent(Serial port) {
  String input = port.readStringUntil('\n');
  if (input == null) return;

  input = input.trim();

  try {
    String[] parts = input.split(",");
    if (parts.length != 2) return;

    float angle = float(parts[0].trim());
    float dist = float(parts[1].trim());

    if (angle >= 0 && angle <= 180) {
      float visualAngle = 180 - angle;
      sweepAngle = visualAngle;

      // 只添加有效距离内的探测点
      if (dist >= 0 && dist <= maxDistance) {
        addDetection(visualAngle, dist);
      }
    }
  } catch (Exception e) {
    println("解析错误: " + input);
  }
}

// --------------------- 雷达网格 ---------------------

void drawRadarGrid() {
  stroke(0, 255, 0);
  strokeWeight(1);
  noFill();

  // 同心圆（每10cm）
  for (int i = 10; i <= maxDistance; i += 10) {
    float r = map(i, 0, maxDistance, 0, radius);
    arc(center.x, center.y, 2 * r, 2 * r, PI, TWO_PI);
  }

  // 角度线与角度文字（每30°）
  for (int angle = 0; angle <= 180; angle += 30) {
    float rad = radians(angle);
    float x = center.x + radius * cos(rad);
    float y = center.y - radius * sin(rad);
    line(center.x, center.y, x, y);

    fill(0, 255, 0);
    textAlign(CENTER, CENTER);
    float tx = center.x + (radius + 20) * cos(rad);
    float ty = center.y - (radius + 20) * sin(rad);
    text(angle + "°", tx, ty);
  }

  // 文字标题
  fill(0, 255, 0);
  textAlign(LEFT);
  text("Radar Range: 0–50 cm", 10, 20);

  // 横坐标：左右距离标签
  textAlign(CENTER);
  fill(0, 255, 0);
  for (int i = 0; i <= maxDistance; i += 10) {
    float r = map(i, 0, maxDistance, 0, radius);
    float xRight = center.x + r;
    float xLeft = center.x - r;
    float y = center.y + 15;  // 稍微低于中心点

    text(i + " cm", xRight, y);
    if (i != 0) text(i + " cm", xLeft, y);  // 避免重复绘制 0 cm
  }
}


// --------------------- 扫描扇形光束 ---------------------

void drawSweepBeam() {
  // 检测方向
  sweepRightToLeft = sweepAngle < lastSweepAngle;
  lastSweepAngle = sweepAngle;

  // 添加当前角度到历史
  beamHistory.add(0, sweepAngle);
  if (beamHistory.size() > beamTrailLength) {
    beamHistory.remove(beamHistory.size() - 1);
  }

  float extendedRadius = radius * 1.15;
  noStroke();

  for (int i = 0; i < beamHistory.size() - 1; i++) {
    float a1 = beamHistory.get(i);
    float a2 = beamHistory.get(i + 1);

    // 忽略不连续（方向跳变）情况
    if (abs(a1 - a2) > 40) continue;

    float alpha = map(i, 0, beamTrailLength - 1, 180, 0);
    fill(0, 255, 0, alpha);

    float aMin = min(a1, a2);
    float aMax = max(a1, a2);

    beginShape(TRIANGLE_FAN);
    vertex(center.x, center.y);
    for (float a = aMin; a <= aMax; a += 0.5) {
      float rad = radians(a);
      float x = center.x + extendedRadius * cos(rad);
      float y = center.y - extendedRadius * sin(rad);
      vertex(x, y);
    }
    endShape(CLOSE);
  }
}



// --------------------- 检测点类 ---------------------

class Detection {
  float angle;
  float distance;
  float alpha;

  Detection(float angle, float distance) {
    this.angle = angle;
    this.distance = distance;
    this.alpha = 180;  // 初始透明度
  }

  void update() {
    alpha -= 2;
  }

  boolean isVisible() {
    return alpha > 0;
  }

  void display() {
    if (distance < 0 || distance > maxDistance) return;

    float r1 = map(distance, 0, maxDistance, 0, radius);
    float r2 = map(maxDistance, 0, maxDistance, 0, radius);
    float rad = radians(angle);

    float x1 = center.x + r1 * cos(rad);
    float y1 = center.y - r1 * sin(rad);
    float x2 = center.x + r2 * cos(rad);
    float y2 = center.y - r2 * sin(rad);

    stroke(255, 0, 0, alpha);
    strokeWeight(2);
    line(x1, y1, x2, y2);
  }
}

// --------------------- 检测点管理 ---------------------

void addDetection(float angle, float distance) {
  if (distance >= 0 && distance <= maxDistance) {
    detections.add(new Detection(angle, distance));
  }
}

void drawDetections() {
  for (int i = detections.size() - 1; i >= 0; i--) {
    Detection d = detections.get(i);
    d.display();
    d.update();
    if (!d.isVisible()) {
      detections.remove(i);
    }
  }
}